What?老板让我开发一个亿级流量的大型网站
以下文章来源于geekhalo ,作者wenxinzizhu
我们常见的大型网站,如百度、淘宝、京东等,都是一个分布式系统。这么复杂的系统也不是一天建成的,每个系统都经历了漫长的演变过程。
支撑海量数据
非常高的访问量
单机系统
单机部署方案
class 文件、依赖 jar 等。
js、css、图片等静态资源。
对于用户上传文件的场景,直接在服务器上新建一个目录,将上传的文件放置在目录即可。
然后,将打好的发布包放到 Web 容器中,比如 Tomcat,最后启动容器,让其直接对外提供服务。
用户通过浏览器直接与 Java 应用程序进行交互(通常是 Tomcat)。
Java 应用程序通过 JDBC 与本机的数据库进行交互(如 MySQL)。
如果存在文件读写的需求,Java 应用程序通过文件接口直接对文件进行操作。
单机部署方案进阶
我们在单机部署基础上,添加 Nginx,也就有了进阶方案:
用户不在直接与 Java 应用程序进行交互,而是与 Nginx 进行交互。
Tomcat 挂在 Nginx 后,对动态请求进行处理。
对于静态资源的访问,通过 Nginx 直接访问文件系统。
当有文件写需求时,通过 Java 应用程序直接写入磁盘。
动静分离部署方案
由于静态请求与动态请求采用不同的处理策略,我们可以将其进行分离。
通过不同的域名对动态请求和静态请求进行分离。
新增静态资源服务器,专门处理静态请求,并在服务器上部署 Java 应用程序,处理文件写需求;Nginx 只负责文件的读操作。
对动态请求进行独立部署,应用程序将文件的写请求转发到静态服务器进行处理。
答案就是云服务,比如阿里云的 OSS 提供静态资源存储服务。CDN 提供访问加速服务,两者结合使用,就得到了一个海量容量并且性能超强的静态资源服务器(集群)。
结合 OSS 和 CDN,静态请求不会成为系统的瓶颈,因此,接下来只对动态请求进行讨论。
应用集群化部署
此时,我们需要将系统中的多个组件部署到不同的服务器上。
对 Nginx 进行独立部署,形成 Web 集群。
对 Java 应用程序进行独立部署,形成应用集群。
对数据库进行独立部署。
Web 集群与应用集群间通过 HTTP 协议进行交互。
应用集群与数据库间通过 JDBC 协议进行交互。
DNS 轮询
大多域名注册商都支持多条 A 记录的解析,其实这就是 DNS 轮询,DNS 服务器将解析请求按照 A 记录的顺序,逐一分配到不同的 IP 上,这样就完成了简单的负载均衡。
负载均衡器
会话问题
①Session Sticky
这种方案主要由 Nginx 处理,让同样 Session 请求每次都发送到同一台服务器进行处理。
Web 服务器重启 Session 丢失。
负载均衡需要进行应用层解析(第 7 层),性能损耗较大。
负载均衡器变为一个有状态的点,不易容灾。
②Session Replication
会话问题的根源在于 Session 由多个应用维护,我们可以使用某种机制,在多台 Web 服务间进行 Session 的数据同步。
造成网络开销。
每台 Web 服务器都保存所有的 Session,内存开销大。
③集中式 Session
我们可以将 Session 从 Web 服务中抽取出来,并对其进行集中存储。
读取 Session 引入了网络开销。
存储设施问题影响应用。
④Cookie Based Session
还可以将 Session 数据放在 Cookie 中,然后在 Web 服务器上从 Cookie 中生成对应的 Session 数据。
受到 Cookie 大小的限制。
存在安全性问题。
每次都携带巨大的 Cookie,带宽消耗严重。
每次都进行 Session 数据恢复,加大应用服务器的负担。
数据库读写分离
通常情况下,数据库的读会成为系统的瓶颈。对此,我们可以使用数据库主从机制,通过添加多个从库来减缓读压力。
对数据库实施主从部署策略。
对于数据的写请求,只能在主库上进行。
对于数据的读请求,可以在任意的从库上进行。
主库与从库间,通过数据库同步策略进行数据同步。
引入搜索和缓存
针对数据库的 like 语句,通常情况下,是通过引入搜索引擎来解决;而热点数据的访问加速,是通过引入缓存服务来解决。
添加搜索集群,用以提升数据检索性能。
添加缓存集群,用以提升热点数据访问性能。
数据库分库分表
随着数据量的增长,写请求量的增加,数据库的写入逐渐成为了瓶颈。常规的写性能优化便是对数据库进行分库分表。
垂直拆分
将不同的业务数据放到不同的数据库实例中。
水平切分
应用垂直拆分
面对一个巨无霸式的应用,就像面对一团毛线团,总有一种无法下手的感觉。对此,可以将其进行拆分,将其拆分为多个应用,每个应用独立开发、独立部署、独立维护。
通过不同的域名或 URL 将整个系统分解为多个子系统。
用户通过浏览器将各子系统拼接成一个完整的系统。
各系统间存在少量交互,甚至没有交互。
服务化架构
我们可以将通用功能封装成一个服务,独立开发、独立部署、独立维护。
整理各个系统间通用业务功能,将其封装为服务,以承载核心业务逻辑,构建成服务集群。
原来的子系统或子频道,变成薄薄的一层,不承载核心业务,只是根据业务流程对业务服务进行编排。
应用服务与业务服务间通过 HTTP 或其他协议进行通信,常见的包括 Dubbo、Thrift 等。
引入消息队列
服务化解决了直接调用问题,对于异步调用,最常见的便是消息中间件。
小结
作者:李涛
编辑:陶家龙、孙淑娟
出处:转载自微信公众号geekhalo
精彩文章推荐: